package masterjava.reporting.client;

import com.extjs.gxt.ui.client.data.TreeLoader;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.widget.Component;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.form.StoreFilterField;
import com.extjs.gxt.ui.client.widget.layout.FlowLayout;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.rpc.AsyncCallback;
import masterjava.common.client.gwt.rpc.CallbackAdapter;
import masterjava.common.client.gxt.base.RootLayout;
import masterjava.common.client.gxt.base.info.InfoPanel;
import masterjava.common.client.gxt.base.model.GenericListener;
import masterjava.common.client.gxt.base.model.GenericModelType;
import masterjava.common.client.gxt.base.rpc.MaskCallbackAdapter;
import masterjava.common.client.gxt.base.tree.*;
import masterjava.common.client.gxt.highstock.ConfiguredHighStockTabs;
import masterjava.common.client.gxt.highstock.HighStockTabs;
import masterjava.common.client.gxt.highstock.HighStockType;
import masterjava.common.client.gxt.highstock.intraday.IntradayHighStockSeries;
import masterjava.common.client.gxt.highstock.intraday.IntradayVolumeHighStockSeries;
import masterjava.common.shared.Converter;
import masterjava.common.shared.HasKey;
import masterjava.common.shared.charts.IntradaysEntry;
import masterjava.common.shared.util.SharedUtil;
import masterjava.reporting.client.dao.AlgoStrategyDao;
import masterjava.reporting.client.dao.TimestampDataDao;
import masterjava.reporting.shared.ReportingSettingKeys;
import masterjava.reporting.shared.entity.AlgoStrategy;
import masterjava.reporting.shared.entity.TimestampData;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * User: gkislin
 * Date: 8/1/11
 */
public class ReportingNavigation extends LayoutContainer {
    private static final int NUMBER = 500;

    private class TestEntry implements IntradaysEntry {
        private final Date timestamp;
        private final Double value;
        private final Double volume;

        private TestEntry(Date ts, Double value, Double volume) {
            this.timestamp = ts;
            this.value = value;
            this.volume = volume;
        }

        @Override
        public Date getTimestamp() {
            return timestamp;
        }

        @Override
        public Double getValue() {
            return value;
        }

        @Override
        public Double getVolume() {
            return volume;
        }
    }


    @Override
    protected void onRender(Element parent, int index) {
        super.onRender(parent, index);

        setLayout(new FlowLayout(10));

        // tree loader
        TreeLoader<GenericTreeModel> loader = new GenericTreeLoader<AlgoStrategy>(new NodeLoader<AlgoStrategy>() {
            @Override
            public List<? extends GenericTreeModel> getRootList() {
                return Collections.singletonList(new FolderModel(
                        new HasKey() {
                            @Override
                            public String getKey() {
                                return "TestUser";
                            }
                        }, 1l, GenericModelType.USER));
            }

            @Override
            public void processNodeList(final GenericTreeModel node, final AsyncCallback<List<? extends GenericTreeModel>> treeCallback) {
                switch (node.getType()) {
                    case USER:
                        AlgoStrategyDao.get().getByUserId(1l,
                                new CallbackAdapter<List<AlgoStrategy>>() {
                                    @Override
                                    protected void process(List<AlgoStrategy> list) {
                                        list = new ArrayList<AlgoStrategy>(3) {
                                            {
                                                add(new AlgoStrategy("Name1", 1l));
                                                add(new AlgoStrategy("AlgoStrategy8", 12l));
                                                add(new AlgoStrategy("SuperAlgo", 3l));
                                                add(new AlgoStrategy("Name16", 4l));
                                            }
                                        };
                                        List<GenericTreeModel> modelList = SharedUtil.convertList(list, new Converter<AlgoStrategy, GenericTreeModel>() {
                                            @Override
                                            public GenericTreeModel convert(AlgoStrategy strategy) {
                                                return new FolderModel(strategy, strategy.getId(), GenericModelType.STRATEGY_TYPE);
                                            }
                                        });
                                        treeCallback.onSuccess(modelList);
                                    }
                                });

                        break;
                    case STRATEGY_TYPE:
                        AlgoStrategyDao.get().getByUserId(1l,
                                new CallbackAdapter<List<AlgoStrategy>>() {
                                    @Override
                                    protected void process(List<AlgoStrategy> list) {
                                        list = new ArrayList<AlgoStrategy>(3) {
                                            {
                                                add(new AlgoStrategy(node.getKey() + "_Inst1", node.getId() * 1000 + 1));
                                                add(new AlgoStrategy(node.getKey() + "_Inst2", node.getId() * 1000 + 2));
                                                add(new AlgoStrategy(node.getKey() + "_Inst3", node.getId() * 1000 + 3));
                                                add(new AlgoStrategy(node.getKey() + "_Inst4", node.getId() * 1000 + 4));
                                            }
                                        };
                                        List<GenericTreeModel> modelList = SharedUtil.convertList(list, new Converter<AlgoStrategy, GenericTreeModel>() {
                                            @Override
                                            public GenericTreeModel convert(AlgoStrategy strategy) {
                                                return new GenericTreeModel(strategy, strategy.getId(), GenericModelType.STRATEGY_INSTANCE);
                                            }
                                        });
                                        treeCallback.onSuccess(modelList);
                                    }
                                });

                        break;
                }
            }
        });
        final GenericTreePanel treePanel = new GenericTreePanel(loader);
        StoreFilterField<GenericTreeModel> filter = treePanel.bindFilter();
        treePanel.addListener(Events.OnClick, new GenericListener<GenericTreeModel>() {
            @Override
            public void onEvent(GenericTreeModel item) {
                Long id = item.getId();
                Component newContent = null;

                switch (item.getType()) {
                    case STRATEGY_TYPE:
                        newContent = InfoPanel.getInfoPanel(ReportingSettingKeys.reportingRobotTypeTemplate);
                        break;
                    case STRATEGY_INSTANCE:
                        final HighStockTabs hsTabs = new ConfiguredHighStockTabs(HighStockType.getTypesMap().values());
                        TimestampDataDao.get().getByDataId(1l, new MaskCallbackAdapter<List<TimestampData>>(hsTabs) {
                            @Override
                            protected void process(List<TimestampData> result) {
                                unmask();
                                List<TestEntry> list = new ArrayList<TestEntry>(NUMBER);
                                List<TestEntry> list2 = new ArrayList<TestEntry>(NUMBER);
                                long now = new Date().getTime();
                                Double plBase = 30.;
                                int shift = 50000000 / NUMBER;
                                for (int i = 0; i< NUMBER; i++) {
                                    now += Random.nextInt(shift);
                                    plBase += (Random.nextDouble() - .3) * 1.;
                                    list.add(new TestEntry(new Date(now), plBase, Random.nextDouble() * 1000.));
                                    list2.add(new TestEntry(new Date(now + 100), plBase - 7., Random.nextDouble() * 1000.));
                                }
                                hsTabs.setSeries(
                                        new IntradayHighStockSeries<TestEntry>(list),
                                        new IntradayHighStockSeries<TestEntry>(list2),
                                        new IntradayVolumeHighStockSeries<TestEntry>(list),
                                        new IntradayVolumeHighStockSeries<TestEntry>(list2));
                            }
                        });
                        newContent = hsTabs;
                        break;
                    case USER:
                        break;
                }
                if (newContent != null) {
                    RootLayout.get().setContent(newContent);
                }
            }
        });
        add(filter);
        add(treePanel);
    }
}
